package com.gzc.just.play.last.war.common.share.performance;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

/**
 * Performance monitoring aspect
 * Monitor method execution performance
 */
@Aspect
@Component
public class PerformanceAspect {

    private static final Logger log = LoggerFactory.getLogger(PerformanceAspect.class);
    private final PerformanceMonitor performanceMonitor;
    
    public PerformanceAspect(PerformanceMonitor performanceMonitor) {
        this.performanceMonitor = performanceMonitor;
    }

    /**
     * Monitor methods with @Monitored annotation
     */
    @Around("@annotation(monitored)")
    public Object monitorMethod(ProceedingJoinPoint joinPoint, Monitored monitored) throws Throwable {
        String methodName = joinPoint.getSignature().toShortString();
        String timerName = monitored.value().isEmpty() ? methodName : monitored.value();
        boolean logParameters = monitored.logParameters();
        boolean logResult = monitored.logResult();
        long thresholdMs = monitored.thresholdMs();
        
        // Record start time
        long startTime = System.currentTimeMillis();
        Object[] args = joinPoint.getArgs();
        
        // Log call
        if (logParameters) {
            log.debug("Calling {} with arguments: {}", methodName, args);
        }
        
        try {
            // Execute target method
            Object result = joinPoint.proceed();
            
            // Calculate execution time
            long duration = System.currentTimeMillis() - startTime;
            
            // Record performance metrics
            performanceMonitor.recordTimer(timerName, duration);
            performanceMonitor.incrementCounter(timerName + ".count");
            
            // Log result
            if (logResult) {
                log.debug("Method {} returned: {} ({}ms)", methodName, result, duration);
            }
            
            // Check performance threshold
            if (duration > thresholdMs) {
                log.warn("Method {} took {}ms (threshold: {}ms)", methodName, duration, thresholdMs);
                performanceMonitor.incrementCounter("slow_method_calls");
            }
            
            return result;
        } catch (Exception e) {
            // Calculate execution time
            long duration = System.currentTimeMillis() - startTime;
            
            // Record performance metrics
            performanceMonitor.recordTimer(timerName + ".error", duration);
            performanceMonitor.incrementCounter(timerName + ".error_count");
            performanceMonitor.recordError();
            
            log.error("Method {} failed after {}ms", methodName, duration, e);
            throw e;
        }
    }
}